home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / python / maclibnx.lha / ls.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-14  |  3.8 KB  |  229 lines

  1. /* An ls-like program for use as an MPW tool.
  2.    Main improvement over the MPW built-in command Files is columnar
  3.    output.  Main disadvantage is the absence of a "-l" flag.
  4.    Public domain by Guido van Rossum, CWI, Amsterdam (July 1987).
  5. */
  6.  
  7. #include <stdio.h>
  8. #include "dir.h"
  9. #include "stat.h"
  10.  
  11. #include "macdefs.h"
  12.  
  13. char *strcpy();
  14.  
  15. int
  16. main(argc, argv)
  17.     int argc;
  18.     char **argv;
  19. {
  20.     setvbuf(stdout, (char*) NULL, _IOLBF, BUFSIZ);
  21.     if (argc > 1)
  22.         lslist(argc-1, argv+1);
  23.     else
  24.         lsdir(":");
  25.     return 0;
  26. }
  27.  
  28. struct item {
  29.     char *name;
  30.     long flags;
  31. };
  32.  
  33. #define ISDIR 1        /* flag set for directory */
  34.  
  35. int
  36. compare(a, b)
  37.     struct item *a, *b;
  38. {
  39.     return IUMagString(a->name, b->name,
  40.         strlen(a->name), strlen(b->name));
  41. }
  42.  
  43. outsortedlist(listc, listv)
  44.     int listc;
  45.     struct item *listv;
  46. {
  47.     qsort(listv, listc, sizeof(struct item), compare);
  48.     outlist(listc, listv, 0, 0);
  49. }
  50.  
  51. outlist(listc, listv, colwidth, screenwidth)
  52.     int listc;
  53.     struct item *listv;
  54.     int colwidth;
  55.     int screenwidth;
  56. {
  57.     int i, j, ncols, nrows;
  58.     char *p;
  59.     
  60.     if (colwidth <= 1) colwidth= 16;
  61.     if (screenwidth <= 1) screenwidth= 72;
  62.     ncols= screenwidth/colwidth;
  63.     nrows= (listc+ncols-1) / ncols;
  64.     
  65.     for (i= 0; i < nrows; ++i) {
  66.         for (j= i; j < listc; j += nrows) {
  67.             if (listv[j].flags & ISDIR) {
  68.                 char buf[40];
  69.                 sprintf(buf, ":%s:", listv[j].name);
  70.                 p= buf;
  71.             }
  72.             else
  73.                 p= listv[j].name;
  74.             if (j+nrows < listc)
  75.                 printf("%-*.*s ", colwidth, colwidth, p);
  76.             else
  77.                 printf("%s\n", p);
  78.         }
  79.     }
  80. }
  81.  
  82. lslist(argc, argv)
  83.     int argc;
  84.     char **argv;
  85. {
  86.     struct item *files= NULL;
  87.     struct item *dirs= NULL;
  88.     int nfiles= 0;
  89.     int ndirs= 0;
  90.     struct stat buf;
  91.     int i;
  92.     
  93.     for (i= 0; i < argc; ++i) {
  94.         if (isdir(argv[i]))
  95.             addtolist(argv[i], &dirs, &ndirs, ISDIR);
  96.         else if (stat(argv[i], &buf) >= 0)
  97.             addtolist(argv[i], &files, &nfiles, 0);
  98.         else
  99.             fprintf(stderr, "Can't stat %s\n", argv[i]);
  100.     }
  101.     outsortedlist(nfiles, files);
  102.     qsort(dirs, ndirs, sizeof(struct item), compare);
  103.     for (i= 0; i < ndirs; ++i) {
  104.         printf("\n%s\n", dirs[i]);
  105.         lsdir(dirs[i]);
  106.     }
  107. }
  108.  
  109. /* "Intelligent" filename concatenation.  Buf becomes path:name, but:
  110.    insert a SEP only if path doesn't end in SEP and name doesn't
  111.    begin with SEP; remove a SEP if path ends in SEP and name begins
  112.    with SEP. Returns buf. */
  113.  
  114. char *
  115. mkpath(buf, path, name)
  116.     char *buf;
  117.     char *path;
  118.     char *name;
  119. {
  120.     char *p;
  121.     
  122.     strcpy(buf, path);
  123.     p= buf + strlen(buf);
  124.     if (p > buf) {
  125.         if (p[-1] != SEP) {
  126.             if (name[0] != SEP)
  127.                 *p++= SEP;
  128.         }
  129.         else if (name[0] == SEP)
  130.             ++name;
  131.     }
  132.     strcpy(p, name);
  133.     return buf;
  134. }
  135.  
  136. lsdir(dir)
  137.     char *dir;
  138. {
  139.     DIR *dirp= opendir(dir);
  140.     struct direct *dp;
  141.     struct item *listv= NULL;
  142.     int listc= 0;
  143.     char buf[256];
  144.     
  145.     if (dirp == NULL) {
  146.         fprintf("can't open directory %s\n", dir);
  147.         return -1;
  148.     }
  149.     while ((dp= readdir(dirp)) != NULL)
  150.         addtolist(dp->d_name, &listv, &listc,
  151.             isdir(mkpath(buf, dir, dp->d_name)) ? ISDIR : 0);
  152.     closedir(dirp);
  153.     if (listc > 0) {
  154.         outsortedlist(listc, listv);
  155.         while (--listc >= 0)
  156.             freemem(listv[listc]);
  157.         freemem((char*) listv);
  158.     }
  159. }
  160.  
  161. char *malloc();
  162. char **realloc();
  163.  
  164. char *
  165. getmem(n)
  166.     int n;
  167. {
  168.     char *p= malloc((unsigned) n);
  169.     
  170.     if (p == 0)
  171.         memexh();
  172.     return p;
  173. }
  174.  
  175. regetmem(ps, n)
  176.     char **ps;
  177.     int n;
  178. {
  179.     if (*ps == NULL)
  180.         *ps= getmem(n);
  181.     else {
  182.         *ps= realloc(*ps, (unsigned) n);
  183.         if (*ps == NULL)
  184.             memexh();
  185.     }
  186. }
  187.  
  188. freemem(p)
  189.     char *p;
  190. {
  191.     free(p);
  192. }
  193.  
  194. memexh()
  195. {
  196.     fprintf(stderr, "out of memory\n");
  197.     exit(3);
  198. }
  199.  
  200. char *
  201. strdup(s)
  202.     char *s;
  203. {
  204.     char *p= getmem(strlen(s)+1);
  205.     
  206.     return strcpy(p, s);
  207. }
  208.  
  209. addtolist(s, plistv, plistc, flags)
  210.     char *s;
  211.     struct item **plistv;
  212.     int *plistc;
  213.     int flags;
  214. {
  215.     regetmem(& (char *) *plistv, (*plistc+1) * sizeof(**plistv));
  216.  
  217.     (*plistv)[*plistc].name= strdup(s);
  218.     (*plistv)[*plistc].flags= flags;
  219.     ++*plistc;
  220. }
  221.  
  222. isdir(path)
  223.     char *path;
  224. {
  225.     struct stat buf;
  226.     
  227.     return stat(path, &buf) == 0 && (buf.st_mode&S_IFMT) == S_IFDIR;
  228. }
  229.